home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / Form / Sources / EditCmd.cpp < prev    next >
Encoding:
Text File  |  1996-04-25  |  15.8 KB  |  481 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                EditCmd.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Author:                Laurent Delamare
  7. //
  8. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #include "Form.hpp"
  13.  
  14. #ifndef EDITCMD_H
  15. #include "EditCmd.h"
  16. #endif
  17.  
  18. #ifndef FWEDVIEW_H
  19. #include "FWEdView.h"
  20. #endif
  21.  
  22. #ifndef FWFRAME_H
  23. #include "FWFrame.h"
  24. #endif
  25.  
  26. #ifndef FWPART_H
  27. #include "FWPart.h"
  28. #endif
  29.  
  30. #ifndef FWUTIL_H
  31. #include "FWUtil.h"
  32. #endif
  33.  
  34. //========================================================================================
  35. // RunTime Info
  36. //========================================================================================
  37.  
  38. #ifdef FW_BUILD_MAC
  39. #pragma segment odfform
  40. #endif
  41.  
  42. FW_DEFINE_AUTO(CEditViewCommand)
  43.  
  44. //========================================================================================
  45. //    class FW_CEditViewCommand
  46. //========================================================================================
  47.  
  48. //----------------------------------------------------------------------------------------
  49. //    CEditViewCommand constructor
  50. //----------------------------------------------------------------------------------------
  51. CEditViewCommand::CEditViewCommand(Environment* ev, 
  52.                             ODCommandID commandID,
  53.                             FW_CFrame* frame,
  54.                             FW_Boolean canUndo)
  55. :    FW_CClipboardCommand(ev, commandID, frame, canUndo),
  56.     FW_MReceiver(),
  57.     fOwnsSelection(false),
  58.     fEditView(0),
  59.     fStartOffset(0),
  60.     fEndOffset(0)
  61. {
  62. }
  63.  
  64. //----------------------------------------------------------------------------------------
  65. //    CEditViewCommand destructor
  66. //----------------------------------------------------------------------------------------
  67.  
  68. CEditViewCommand::~CEditViewCommand()
  69. {
  70.     if (fOwnsSelection)
  71.         delete fSelection;        // Selection was created on the fly in DoMenu
  72. }
  73.  
  74. //----------------------------------------------------------------------------------------
  75. //    CEditViewCommand::SetEditView
  76. //----------------------------------------------------------------------------------------
  77. // SetEditView must be called right after the creation of the CEditViewCommand in order
  78. // to initialize the fEditView attribut because FW_CFrame::NewClipboardCommand doesn't let
  79. // us pass arguments.  See CScrollEdit::DoMenu().
  80.  
  81. void CEditViewCommand::SetEditView(FW_CEditView* editView)
  82. {
  83.     fEditView = editView;
  84.     
  85.     // [LSD] work-around to notify & disable the command when the edit view is deleted
  86.     // See CEditViewCommand::HandleNotification
  87.     AddInterest(FW_CInterest(editView, FW_kNotifierDeletedMsg));
  88. }
  89.  
  90. //----------------------------------------------------------------------------------------
  91. //    CEditViewCommand::HandleNotification
  92. //----------------------------------------------------------------------------------------
  93. // 
  94. void CEditViewCommand::HandleNotification(Environment* ev, const FW_CNotification& notification) 
  95. {
  96.     if (notification.GetMessage() == FW_kNotifierDeletedMsg)
  97.     {
  98.         // [LSD] The edit view associated with this command has been deleted.  We cannot
  99.         // delete the command ourselves, it belongs to OpenDoc Undo stack, but we must
  100.         // disable it to avoid any trouble in RedoIt & UndoIt.
  101.         fEditView = 0;
  102.     }
  103. }
  104.  
  105. //----------------------------------------------------------------------------------------
  106. //    CEditViewCommand::PreCommand
  107. //----------------------------------------------------------------------------------------
  108.  
  109. void CEditViewCommand::PreCommand(Environment* ev)
  110. {
  111.     ODCommandID id = GetCommandID(ev);
  112.     
  113.     if ((id == kODCommandCopy) || (id == kODCommandCut))
  114.         fEditView->DoTECommand(ev, kODCommandCopy, false);    // Tell TE to copy the text
  115. }
  116.  
  117. //----------------------------------------------------------------------------------------
  118. //    CEditViewCommand::CommandDone
  119. //----------------------------------------------------------------------------------------
  120. /*
  121. void CEditViewCommand::CommandDone(Environment* ev)
  122. {
  123.     // If fEditView belongs to your part's content you may want to notify it of the change
  124.     switch (GetCommandID(ev))
  125.     {
  126.         case kODCommandCut:
  127.         case kODCommandPaste:
  128.         case kODCommandClear:
  129.             fEditView->Notify(ev, CEditNotification(fEditView));
  130.     }
  131. }
  132. */
  133.  
  134. //----------------------------------------------------------------------------------------
  135. //    CEditViewCommand::SaveUndoState
  136. //----------------------------------------------------------------------------------------
  137. void CEditViewCommand::SaveUndoState(Environment* ev)
  138. {
  139.     switch (GetCommandID(ev))
  140.     {
  141.         case kODCommandCut:
  142.         case kODCommandClear:
  143.             fPastedText = fEditView->GetSelectedText(ev);
  144.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  145.             break;
  146.  
  147.         case kODCommandPaste:
  148.             fSavedText = fEditView->GetSelectedText(ev);
  149.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  150.             break;
  151.     }
  152. }
  153.  
  154. //----------------------------------------------------------------------------------------
  155. //    CEditViewCommand::SaveRedoState
  156. //----------------------------------------------------------------------------------------
  157. void CEditViewCommand::SaveRedoState(Environment* ev)
  158. {
  159.     if (GetCommandID(ev) == kODCommandPaste)
  160.     {
  161.         CEditViewSelContent* selContent = (CEditViewSelContent*)fSelection->GetSelectedContent(ev);
  162.         fPastedText = selContent->GetInternalizedText(ev);
  163.     }
  164. }
  165.  
  166. //----------------------------------------------------------------------------------------
  167. //    CEditViewCommand::UndoIt
  168. //----------------------------------------------------------------------------------------
  169.  
  170. void CEditViewCommand::UndoIt(Environment* ev)
  171. {
  172.     FW_CClipboardCommand::UndoIt(ev);    // call inherited
  173.  
  174.     // Don't do anything if command is disabled
  175.     if (fEditView == NULL)
  176.         return;
  177.         
  178.     switch (GetCommandID(ev))
  179.     {
  180.         case kODCommandCut:
  181.         case kODCommandClear:
  182.             this->RestoreText(ev);
  183.             break;
  184.  
  185.         case kODCommandPaste:
  186.             this->RemoveAndRestoreText(ev, fPastedText.GetByteLength(), fSavedText);
  187.             break;
  188.     }    
  189. }
  190.  
  191. //----------------------------------------------------------------------------------------
  192. //    CEditViewCommand::RedoIt
  193. //----------------------------------------------------------------------------------------
  194. void CEditViewCommand::RedoIt(Environment* ev)
  195. {
  196.     FW_CClipboardCommand::RedoIt(ev);    // call inherited
  197.  
  198.     // Don't do anything if command is disabled
  199.     if (fEditView == NULL)
  200.         return;
  201.  
  202.     switch (GetCommandID(ev))
  203.     {
  204.         case kODCommandCut:
  205.         case kODCommandClear:
  206.             this->RemoveText(ev);
  207.             break;
  208.  
  209.         case kODCommandPaste:
  210.             this->RemoveAndRestoreText(ev, fSavedText.GetByteLength(), fPastedText);
  211.             break;
  212.     }    
  213. }
  214.  
  215. //----------------------------------------------------------------------------------------
  216. //    CEditViewCommand::RemoveText
  217. //----------------------------------------------------------------------------------------
  218.  
  219. void CEditViewCommand::RemoveText(Environment* ev)
  220. {
  221.     FW_ASSERT(fEditView);
  222.  
  223.     fEditView->SelectText(ev, fStartOffset, fEndOffset);
  224.     fEditView->DoTECommand(ev, kODCommandClear, false);
  225.  
  226.     // If fEditView belongs to your part's content you may want to notify it of the change
  227. //    fEditView->Notify(ev, CEditNotification(fEditView));
  228. }
  229.  
  230. //----------------------------------------------------------------------------------------
  231. //    CEditViewCommand::RestoreText
  232. //----------------------------------------------------------------------------------------
  233.  
  234. void CEditViewCommand::RestoreText(Environment* ev)
  235. {
  236.     FW_ASSERT(fEditView);
  237.  
  238.     // Insert the saved text back into the EditView
  239.     fEditView->InsertText(ev, fPastedText, fStartOffset);
  240.  
  241.     // If fEditView belongs to your part's content you may want to notify it of the change
  242. //    fEditView->Notify(ev, CEditNotification(fEditView));   
  243. }
  244.  
  245. //----------------------------------------------------------------------------------------
  246. //    CEditViewCommand::RemoveAndRestoreText
  247. //----------------------------------------------------------------------------------------
  248.  
  249. void CEditViewCommand::RemoveAndRestoreText(Environment* ev, FW_ByteCount bytesToRemove,
  250.                                                 const FW_CString& textToRestore)
  251. {
  252.     FW_ASSERT(fEditView);
  253.  
  254.     // Remove designated text
  255.     fEditView->SelectText(ev, fStartOffset, fStartOffset+(short)bytesToRemove);
  256.     fEditView->DoTECommand(ev, kODCommandClear, false);
  257.  
  258.     // Restore the text
  259.     fEditView->InsertText(ev, textToRestore, fStartOffset);
  260.  
  261.     // If fEditView belongs to your part's content you may want to notify it of the change
  262. //    fEditView->Notify(ev, CEditNotification(fEditView));
  263. }
  264.  
  265. #pragma mark -
  266. //========================================================================================
  267. //    CLASS CEditViewSelection
  268. //========================================================================================
  269.  
  270. FW_DEFINE_AUTO(CEditViewSelection)
  271.  
  272. //---------------------------------------------------------------------------------------
  273. //    CEditViewSelection constructor
  274. //---------------------------------------------------------------------------------------
  275.  
  276. CEditViewSelection::CEditViewSelection(Environment* ev, FW_CEditView* editview) :
  277.     FW_CSelection(ev, false, false),
  278.     fSelectedContent(NULL)
  279. {
  280.     fSelectedContent = FW_NEW(CEditViewSelContent, (ev, editview));
  281. }
  282.  
  283. //---------------------------------------------------------------------------------------
  284. //    CEditViewSelection destructor
  285. //---------------------------------------------------------------------------------------
  286.  
  287. CEditViewSelection::~CEditViewSelection()
  288. {
  289.     delete fSelectedContent;
  290. }
  291.  
  292. //---------------------------------------------------------------------------------------
  293. //    CEditViewSelection::ClearSelection
  294. //---------------------------------------------------------------------------------------
  295.  
  296. void CEditViewSelection::ClearSelection(Environment* ev)
  297. {
  298.     fSelectedContent->ClearSelectedText(ev); 
  299. }
  300.  
  301. //---------------------------------------------------------------------------------------
  302. //    CEditViewSelection::CloseSelection
  303. //---------------------------------------------------------------------------------------
  304.  
  305. void CEditViewSelection::CloseSelection(Environment* ev)
  306. {
  307.     fSelectedContent->UnselectText(ev);
  308. }
  309.  
  310. //---------------------------------------------------------------------------------------
  311. //    CEditViewSelection::IsEmpty
  312. //---------------------------------------------------------------------------------------
  313.  
  314. FW_Boolean CEditViewSelection::IsEmpty(Environment* ev) const
  315. {
  316.     return fSelectedContent->IsEmpty(ev);
  317. }
  318.  
  319. //---------------------------------------------------------------------------------------
  320. //    CEditViewSelection::SelectAll
  321. //---------------------------------------------------------------------------------------
  322.  
  323. void CEditViewSelection::SelectAll(Environment* ev)
  324. {
  325. FW_UNUSED(ev);
  326.     // This function is handled by the current EditView
  327. }
  328.  
  329. #pragma mark -
  330. //========================================================================================
  331. //    CEditViewSelContent class
  332. //========================================================================================
  333.  
  334. FW_DEFINE_AUTO(CEditViewSelContent)
  335.  
  336. //----------------------------------------------------------------------------------------
  337. // CEditViewSelContent constructor
  338. //----------------------------------------------------------------------------------------
  339. CEditViewSelContent::CEditViewSelContent(Environment* ev, FW_CEditView* editview) :
  340.     FW_CContent(ev, editview->GetFrame(ev)->GetPart(ev)),
  341.     fEditView(editview)
  342. {
  343. }
  344.  
  345. //----------------------------------------------------------------------------------------
  346. // CEditViewSelContent destructor
  347. //----------------------------------------------------------------------------------------
  348.  
  349. CEditViewSelContent::~CEditViewSelContent()
  350. {
  351. }
  352.  
  353. //----------------------------------------------------------------------------------------
  354. // CEditViewSelContent::Externalize
  355. //----------------------------------------------------------------------------------------
  356. void CEditViewSelContent::Externalize(    Environment* ev,
  357.                                     ODStorageUnit* storageUnit,
  358.                                     FW_EStorageKinds storageKind,
  359.                                     FW_CCloneInfo* cloneInfo)
  360. {
  361.     FW_UNUSED(cloneInfo);
  362.     FW_UNUSED(storageKind);
  363.  
  364.     // Externalize in order of fidelity: ODIText, 'TEXT'
  365.     FW_CString selectedText = fEditView->GetSelectedText(ev);
  366.  
  367. /* This doesn't work, because when I Internalize the text it's in the form:
  368.     length word, char, etc. 
  369.     where each character takes up a word instead of a byte.
  370.     // Write the selected string as an ODIText
  371.     ODSetITextProp(ev, storageUnit, kODPropContents, kODIntlText, selectedText.RevealODIText());
  372. */
  373.  
  374.     // Write the selected string in Mac 'TEXT' format
  375.     FW_SUAddPropValue(ev, storageUnit, kODPropContents, FW_CPart::gMacTEXTDataType);
  376.     FW_PStorageUnitSink suSink(ev, storageUnit, kODPropContents, FW_CPart::gMacTEXTDataType);
  377.     FW_CWritableStream stream(suSink);
  378.     stream.Write(selectedText.RevealBuffer(), selectedText.GetByteLength());
  379. }
  380.  
  381. //----------------------------------------------------------------------------------------
  382. // CEditViewSelContent::Internalize
  383. //----------------------------------------------------------------------------------------
  384.  
  385. FW_Boolean CEditViewSelContent::Internalize(Environment* ev,
  386.                                          ODStorageUnit* sourceSU, 
  387.                                          FW_EStorageKinds storageKind,
  388.                                          FW_CCloneInfo* cloneInfo)
  389. {
  390. FW_UNUSED(cloneInfo);
  391. FW_UNUSED(storageKind);
  392.     FW_ASSERT(fEditView);
  393.     
  394.     FW_Boolean internalized = false;
  395.     FW_CString selectedText;
  396.  
  397.     // Compute the maximum number of characters that can be added to the edit view
  398.     short startSel, endSel;
  399.     fEditView->GetSelectionRange(ev, startSel, endSel);
  400.     FW_ByteCount  notSelectedChars = fEditView->GetTextLength(ev) - (endSel - startSel);
  401.     if (notSelectedChars >= fEditView->GetMaxChars(ev))
  402.         return false;
  403.  
  404.     FW_ByteCount  maxChars = fEditView->GetMaxChars(ev) - notSelectedChars;
  405.  
  406. /* See note in Externalize
  407.     // ODIText
  408.     if (FW_SUExistsThenFocus(ev, sourceSU, kODPropContents, kODIntlText))    
  409.         internalized = InternalizeIntlText(ev, sourceSU, selectedText);
  410.     else 
  411. */
  412.     // 'TEXT'
  413.     if (FW_SUExistsThenFocus(ev, sourceSU, kODPropContents, FW_CPart::gMacTEXTDataType))    
  414.         internalized = InternalizeText(ev, sourceSU, selectedText, maxChars);
  415.  
  416.     if (internalized)
  417.     {
  418.         fInternalizedText = selectedText;
  419.         fEditView->SetSelectedText(ev, selectedText);
  420.  
  421. //        if (storageKind != FW_kPartStorage)  
  422. //            fEditView->GetFrame(ev)->GetPart(ev)->PartChanged(ev);
  423.     }
  424.  
  425.     return internalized;
  426. }
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // CEditViewSelContent::ClearSelectedText
  430. //----------------------------------------------------------------------------------------
  431.  
  432. void CEditViewSelContent::ClearSelectedText(Environment* ev)
  433. {
  434.     fEditView->SetSelectedText(ev, FW_CString());
  435. }
  436.  
  437. //----------------------------------------------------------------------------------------
  438. // CEditViewSelContent::UnselectText
  439. //----------------------------------------------------------------------------------------
  440.  
  441. void CEditViewSelContent::UnselectText(Environment* ev)
  442. {
  443.     fEditView->SelectText(ev, 0, 0);    // [LSD] should be at selStart
  444. }
  445.  
  446. //---------------------------------------------------------------------------------------
  447. //    CEditViewSelContent::IsEmpty
  448. //---------------------------------------------------------------------------------------
  449.  
  450. FW_Boolean CEditViewSelContent::IsEmpty(Environment* ev) const
  451. {
  452.     short startOffset, endOffset; 
  453.     fEditView->GetSelectionRange(ev, startOffset, endOffset);
  454.     return (startOffset == endOffset);
  455. }
  456.  
  457. //----------------------------------------------------------------------------------------
  458. //    InternalizeText
  459. //----------------------------------------------------------------------------------------
  460. // Global function to read text fro a storage unit
  461.  
  462. FW_Boolean InternalizeText(Environment* ev, ODStorageUnit* storageUnit, 
  463.                                 FW_CString& text, FW_ByteCount  maxChars)
  464. {
  465.     FW_ByteCount textSize = storageUnit->GetSize(ev);
  466.     if (textSize == 0) 
  467.         return false;
  468.         
  469.     if (textSize > maxChars)
  470.         textSize = maxChars;
  471.         
  472.     FW_CByteArray byteArray;
  473.     storageUnit->GetValue(ev, textSize, byteArray);
  474. //    byteArray.CopyBuffer(&buffer, textSize);
  475.     
  476.     text = FW_CString((char *)byteArray.GetBuffer(), textSize);
  477.     
  478.     return true;
  479. }
  480.  
  481.